#include "DamageSystem.h"

#include "BulletComponent.h"
#include "PhysicComponents.h"
#include "LifeComponent.h"
#include "GraphicComponents.h"
#include "ParticleComponent.h"
#include "PositionComponent.h"

#include "RenderSystem.h"
#include "PhysicSystem.h"
#include "MathUtiles.h"

#include "GameState.h"
#include <cmath>

DamageSystem::DamageSystem()
{

}
void DamageSystem::update(float dt)
{
	std::vector<int> toDelete;

	for(std::deque<int>::iterator itr = mpt_bullets.begin(); itr != mpt_bullets.end();)
	{
		if(entityManager->hasEntity((*itr)))
		{
			// REGARDER SI LA BULLET PERCUTE UN DYNAMIC 

			DynamicComponentPtr bulletPhys = entityManager->getEntity(*itr)->getAs<DynamicComponent>();
			BulletComponentPtr bullet = entityManager->getEntity(*itr)->getAs<BulletComponent>();

			bool killed = false;
			if(bullet->type == BulletComponent::NORMAL || bullet->type == BulletComponent::ZONE)
			{
				for(std::set<int>::iterator itr2 = mpt_entitiesID.begin(); itr2 != mpt_entitiesID.end(); itr2++)
				{
					if(entityManager->hasEntity((*itr2)))
					{
						PositionComponentPtr posE = entityManager->getEntity(*itr)->getAs<PositionComponent>();
						PositionComponentPtr posB = entityManager->getEntity(*itr2)->getAs<PositionComponent>();
						PhysicComponentPtr physB = entityManager->getEntity(*itr2)->getAs<PhysicComponent>();

						sf::FloatRect rectE(posE->m_position - posE->m_center, bulletPhys->sizeBox);
						sf::FloatRect rectB(posB->m_position - posB->m_center, physB->sizeBox);

						LifeComponentPtr lifeC = entityManager->getEntity(*itr2)->getAs<LifeComponent>();

						if(rectE.intersects(rectB) && bullet->IDlauncher != *itr2 && lifeC->life > 0)
						{
							lifeC->life-=bullet->power;
							if(lifeC->life <= 0 && lifeC->killAfterZero)
								toDelete.push_back(*itr2);
							
							if(bullet->type == BulletComponent::NORMAL)
								toDelete.push_back(*itr);

							//CREER UN ENSEMBLE DE PARTICULES AU CRASH (A DONNER AU PARTICULE SYSTEM)
							int random = std::rand()%2 + 3;
							PositionComponentPtr positionBullet = entityManager->getEntity(*itr)->getAs<PositionComponent>();
							GameState* state = static_cast<GameState*>(mpt_parent);
							
							for(int i = 0; i<random; i++)
							{
								ModelGraphicComponentPtr graph(new ModelGraphicComponent);
								JumpingComponentPtr phys(new JumpingComponent);
								ParticleComponentPtr particle(new ParticleComponent);
								PositionComponentPtr position(new PositionComponent);

								graph->model.loadModel("Data/blood.mdl");

								position->m_position = positionBullet->m_position;
								position->m_center = graph->m_transform.getOrigin();

								phys->jumpSpeed = 400.0f;
								phys->jumpLength = 1.5;
								phys->jumpState = getFloatRandom(-0.3f,0.0f);
								phys->speed = 50;
								phys->sizeBox = sf::Vector2f(3.0f,3.0f);

								particle->direction = bulletPhys->normalCollision;
								particle->physic = true;
								particle->time = 0.35f;

								BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
								entityManager->registerDynamicEntity(e, position->m_position,0);
								
								entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
								entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
								entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), position);
								entityManager->addComponent<ParticleComponent>((BPL::EntityId)e->getID(), particle);

								state->mpt_renderSystem->addEntity(e->getID());
								state->mpt_physicSystem->addEntity(e->getID());
								state->mpt_particuleSystem->addEntity(e->getID());
							}
						}
					}
				}

				if(bulletPhys->collide && bullet->IDlauncher != bulletPhys->collideWith)
				{
					if(mpt_entitiesID.find(bulletPhys->collideWith)!=mpt_entitiesID.end())
					{
						LifeComponentPtr lifeC = entityManager->getEntity(bulletPhys->collideWith)->getAs<LifeComponent>();
						lifeC->life-=bullet->power;
						if(lifeC->life < 0 && lifeC->killAfterZero)
						{
							toDelete.push_back(bulletPhys->collideWith);
							killed = true;
						}
						//CREER UN ENSEMBLE DE PARTICULES AU CRASH (A DONNER AU PARTICULE SYSTEM)
						int random = std::rand()%2 + 1;
						PositionComponentPtr positionBullet = entityManager->getEntity(*itr)->getAs<PositionComponent>();
						GameState* state = static_cast<GameState*>(mpt_parent);
						
						for(int i = 0; i<random; i++)
						{
							ModelGraphicComponentPtr graph(new ModelGraphicComponent);
							JumpingComponentPtr phys(new JumpingComponent);
							ParticleComponentPtr particle(new ParticleComponent);
							PositionComponentPtr position(new PositionComponent);

							graph->model.loadModel("Data/blood.mdl");

							position->m_position = positionBullet->m_position;
							position->m_center = graph->m_transform.getOrigin();

							phys->jumpSpeed = 400.0f;
							phys->jumpLength = 1.5;
							phys->jumpState = getFloatRandom(-0.5f,0.2f);
							phys->speed = 50;
							phys->sizeBox = sf::Vector2f(3.0f,3.0f);

							particle->direction = bulletPhys->normalCollision;
							particle->physic = true;
							particle->time = 0.35f;

							BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
							entityManager->registerDynamicEntity(e, position->m_position,0);
							
							entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
							entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
							entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), position);
							entityManager->addComponent<ParticleComponent>((BPL::EntityId)e->getID(), particle);

							state->mpt_renderSystem->addEntity(e->getID());
							state->mpt_physicSystem->addEntity(e->getID());
							state->mpt_particuleSystem->addEntity(e->getID());
						}
					}
				}
			}
			else
			{
				if(bullet->timeElapsed > bullet->timeBeforeDeath)
				{
					killed = true;
					sf::Vector2f posGrenade = entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position;
					for(std::set<int>::iterator itr2 = mpt_entitiesID.begin(); itr2 != mpt_entitiesID.end(); itr2++)
					{
						if(entityManager->hasEntity((*itr2)))
						{
							sf::Vector2f pos = entityManager->getEntity(*itr2)->getAs<PositionComponent>()->m_position;
							float distance = getNorme(pos-posGrenade);

							if(distance < bullet->range)
							{
								LifeComponentPtr lifeC = entityManager->getEntity(*itr2)->getAs<LifeComponent>();
								lifeC->life-=bullet->power;
								if(lifeC->life < 0 && lifeC->killAfterZero)
									toDelete.push_back(*itr2);
							}
						}
					}
				}
			}

			if(bullet->rebounds < 0 || killed)
				toDelete.push_back(*itr);
			itr++;
		}
		else
		{
			BPL::Logger::log("bug DamageSystem");
			BPL::Logger::log(boost::lexical_cast<std::string>(*itr).c_str());
			itr = mpt_bullets.erase(itr);
		}
			
	}

	for(std::vector<int>::iterator toKill = toDelete.begin(); toKill != toDelete.end(); toKill++)
	{
		entityManager->killEntity(*toKill);
	}
}
void DamageSystem::addBullet(int bullet)
{
	if(!entityManager->hasEntity(bullet))
		return;

	mpt_bullets.push_back(bullet);
	entityManager->getEntity(bullet)->addSystem(this);
}

void DamageSystem::deleteEntity(int ent)
{
	std::set<int>::iterator itr = mpt_entitiesID.find(ent);
	if(itr != mpt_entitiesID.end())
		mpt_entitiesID.erase(itr);

	std::deque<int>::iterator itr2;
	for(itr2 = mpt_bullets.begin(); itr2 != mpt_bullets.end(); )
	{
		if(*itr2 == ent)
		{
			mpt_bullets.erase(itr2);
			itr2 = mpt_bullets.end();
#ifdef DEFINE_MODE
			BPL::Logger::log("delete from DamageSystem");
#endif
		}
		else
			itr2++;
	}
}